package org.batatasframework.support.definition.impl;

import java.util.List;

import org.batatasframework.support.database.DatabaseType;
import org.batatasframework.support.database.metadatas.FieldMetadata;
import org.batatasframework.support.database.sql.TableInstance;
import org.batatasframework.support.database.sql.spi.TableCriterion;
import org.batatasframework.support.database.sql.where.QueryFragmentAppender;
import org.batatasframework.support.database.sql.where.SingleQueryFragment;
import org.batatasframework.support.definition.QueryDefinition;
import org.batatasframework.support.definition.TableDefinitionResource;
import org.batatasframework.support.event.HttpRequestAccessor;
import org.batatasframework.support.searchable.FieldQueryed;
import org.batatasframework.support.searchable.FieldQueryedLinkage;

import cn.bonoon.kernel.support.IOperator;
import cn.bonoon.kernel.util.Opt;

/**
 * <pre>
 * 支持查询条件选项是级联下拉的选择项，如：地区选项等。
 * 
 * 注意：选项可以对应去查询不同的字段，但这些字段必须在同一个数据库表里，目前不支持跨表的级联下拉查询。
 * </pre>
 * @author jackson
 *
 */
public class LinkageQueryDefinition implements QueryDefinition{

	private TableDefinitionResource tableDefinitionResource;
	private final Opt[] opts = { Opt.EQ };
	private final String title;
	
	private String idField = "id";
	private String nameField = "text";
	private String paramName = "pid";
	
	private final String url;
	private final String initParam;
	
	private final FieldMetadata column;
	private final FieldMetadata[] columns;
	private final String[] columnStrings;
	
	public void setTableDefinitionResource(TableDefinitionResource tableDefinitionResource) {
		this.tableDefinitionResource = tableDefinitionResource;
	}
	
	public LinkageQueryDefinition(String title, String url, String initParam,
			TableDefinitionResource tableDefinitionResource,
			String column, String...columns){
		
		this.url = url;
		this.initParam = initParam;
		
		this.title = title;
		this.tableDefinitionResource = tableDefinitionResource;
		
		//TableMetadata tableMetadata = tableDefinitionResource.getSourceTableMetadata();
		this.column = tableDefinitionResource.get(column);
		if(null == columns){
			this.columnStrings = new String[0];
			this.columns = new FieldMetadata[0];
		}else{
			this.columnStrings = new String[columns.length];
			this.columns = new FieldMetadata[columns.length];
			int i = 0;
			for(String col : columns){
				this.columnStrings[i] = "_c_" + i;
				this.columns[i++] = tableDefinitionResource.get(col);
			}
		}
	}

	@Override
	public void buildQuery(QueryFragmentAppender queryAppend, TableCriterion tableCriterion, HttpRequestAccessor paramAccessor, String key) throws Exception {
		buildQuery(queryAppend, tableCriterion.safeLoadSource(tableCriterion, tableDefinitionResource, true), paramAccessor, key);
	}

	@Override
	public void buildQuery(QueryFragmentAppender queryAppend, TableInstance tableSource, HttpRequestAccessor paramAccessor, String key) throws Exception {
		parse(queryAppend, tableSource, column, paramAccessor, key, "_c");
		for(int i = 0; i < columns.length; i++){
			parse(queryAppend, tableSource, columns[i], paramAccessor, key, columnStrings[i]);
		}
	}
	
	private void parse(QueryFragmentAppender queryAppend, 
			TableInstance tableSource, FieldMetadata fm, 
			HttpRequestAccessor paramAccessor, String key, String suf) throws Exception{
		Long id = paramAccessor.getLong(key, suf);
		if(null != id && id > 0){
			queryAppend.addQuery(new SingleQueryFragment(tableSource, fm, Opt.EQ, id));
		}
	}
	
	@Override
	public void buildFieldQueryed(List<FieldQueryed> queryColumn, String key, IOperator operator, boolean forceRefresh) {
		queryColumn.add(new FieldQueryedLinkage(
			key, title, idField, nameField, url, initParam, paramName, columnStrings
		));
	}

	@Override
	public DatabaseType getDataType() {
		return DatabaseType.NUMBER;
	}

	@Override
	public Opt[] getOpts() {
		return opts;
	}

	@Override
	public String getTitle() {
		return title;
	}
}
